<?php
require ('SignParam.php');

// S3签名类
class Signature {
	private $subResArray = array (
		"acl",
		"lifecycle",
		"location",
		"logging",
		"notification",
		"partNumber",
		"policy",
		"requestPayment",
		"torrent",
		"uploadId",
		"uploads",
		"versionId",
		"versioning",
		"versions",
		"website" 
	);
	
	/**
	 * 生成签名
	 * @param SignParam $signParam  签名参数
	 * @return string	签名串
	 */
	public function sign(SignParam $signParam) {
		$contentMD5 = "";
		$contentType = "";
		$httpVerb = $signParam->getHttpMethod ();
		$accessKey = $signParam->getAccesskey ();
		$secretKey = $signParam->getSecretKey ();
		$date = $signParam->getZoneDateTime ();
		$resource = $signParam->getUri ();
		// url去#、?符号
		$resource = $this->encodePath ( $resource );
		// 拼接特定的子串
		$resource = $this->subresourcePath ( $resource, $signParam->getParameterNames () );
		
		$stringToSign = $httpVerb . "\n" . $contentMD5 . "\n" . $contentType . "\n" . $date . "\n" . $resource;
		$stringToSign = mb_convert_encoding ( $stringToSign, "UTF-8" );
		$secretKey = mb_convert_encoding ( $secretKey, "UTF-8" );
		// 使用HmacSHA1算法进行加密
		$signature = base64_encode ( hash_hmac ( "sha1", $stringToSign, $secretKey, true ) );
		if ($this->endWith ( $signature, "\r\n" )) {
			$signature = substr ( $signature, 0, strlen ( $signature ) - 2 );
		}
		if ($this->endWith ( $signature, "\n" )) {
			$signature = substr ( $signature, 0, strlen ( $signature ) - 1 );
		}
		$signature = "AWS" . " " . $accessKey . ":" . $signature;
		return $signature;
	}
	
	/**
	 * 如果URI包含?、#符号，就要把URI截取到符号之前为止
	 * @param unknown $uri
	 * @return string
	 */
	public function encodePath($uri) {
		$endPos = strlen ( $uri );
		for($i = 0; $i < $endPos; $i ++) {
			if (strpos ( "?#", $uri [$i] ) > - 1) {
				$endPos = $i;
				break;
			}
		}
		return substr ( $uri, 0, $endPos );
	}
	
	/**
	 * 当url中含有特定名称的参数时， 就在url中把参数名称拼接上
	 * @param unknown $resource
	 * @param array $parameterNames
	 * @return string
	 */
	public function subresourcePath($resource, $parameterNames) {
		if ($parameterNames != null && count ( $parameterNames ) > 0) {
			// 对数组进行升序排列
			sort ( $parameterNames );
			$subRes = $parameterNames [0];
			// 当参数名称在subResArray范围内时，就把它拼接上
			if (in_array ( $subRes, $this->subResArray )) {
				$resource = $resource . "?" . $subRes;
			}
		}
		return $resource;
	}
	
	
	/**
	 * 获取当前时间，使用的时区是零时区
	 * @return string  返回格式参考：Tue, 24 Mar 2020 16:35:24 GMT
	 */
	public function getZoneDateTime() {
		$DATE_RFC1123 = "D, d M Y H:i:s";
		return gmdate ( $DATE_RFC1123 ) . ' GMT';
	}
	
	/**
	 * 判断字符串的结尾
	 * @param unknown $haystack  原串
	 * @param unknown $needle    部分串
	 * @return boolean
	 */
	function endWith($haystack, $needle) {
		$length = strlen ( $needle );
		if ($length == 0) {
			return true;
		}
		return (substr ( $haystack, - $length ) === $needle);
	}
	
}

?>
    
   
    